//
//  LimitedTimeDiscountManager.swift
//  CMB250716
//
//  Created by System on 2024/12/19.
//

import Foundation

/// 限时折扣管理器
class LimitedTimeDiscountManager: ObservableObject {
    
    static let shared = LimitedTimeDiscountManager()
    
    @Published var isDiscountActive: Bool = false
    @Published var nextDiscountTime: Date?
    
    private var timer: Timer?
    
    private init() {
        updateDiscountStatus()
        startTimer()
    }
    
    deinit {
        timer?.invalidate()
    }
    
    // MARK: - Public Methods
    
    /// 检查当前是否在折扣时间段内
    func isCurrentlyInDiscountPeriod() -> Bool {
        let now = Date()
        let calendar = Calendar.current
        let weekday = calendar.component(.weekday, from: now)
        let currentTime = getCurrentTimeString(from: now)
        
        // 周六(7)和周日(1)
        if weekday == 1 || weekday == 7 {
            return isTimeInSlots(currentTime, slots: AppConfig.LimitedTimeDiscount.weekendTimeSlots)
        } else {
            // 周一到周五(2-6)
            return isTimeInSlots(currentTime, slots: AppConfig.LimitedTimeDiscount.weekdayTimeSlots)
        }
    }
    
    /// 检查商品是否适用折扣
    func isItemEligibleForDiscount(_ item: MenuItem) -> Bool {
        return !AppConfig.LimitedTimeDiscount.excludedCategories.contains(item.category)
    }
    
    /// 检查订餐类型是否适用折扣
    func isDiningTypeEligible(_ diningType: DiningType) -> Bool {
        return AppConfig.LimitedTimeDiscount.applicableDiningTypes.contains(diningType)
    }
    
    /// 检查用户是否有资格享受折扣
    func isUserEligibleForDiscount(_ user: User?) -> Bool {
        if AppConfig.LimitedTimeDiscount.requiresMembership {
            return user != nil && user!.membershipLevel.pointsRequired >= 0
        }
        return true
    }
    
    /// 计算折扣后的价格
    func calculateDiscountedPrice(_ originalPrice: Double) -> Double {
        return originalPrice * (1 - AppConfig.LimitedTimeDiscount.discountRate)
    }
    
    /// 获取折扣百分比显示文本
    func getDiscountPercentageText() -> String {
        let percentage = Int(AppConfig.LimitedTimeDiscount.discountRate * 100)
        return "\(percentage)%"
    }
    
    /// 获取下一个折扣时间段
    func getNextDiscountPeriod() -> Date? {
        let now = Date()
        let calendar = Calendar.current
        
        // 检查今天剩余的时间段
        if let nextToday = getNextDiscountTimeToday(from: now) {
            return nextToday
        }
        
        // 检查未来7天内的时间段
        for dayOffset in 1...7 {
            if let futureDate = calendar.date(byAdding: .day, value: dayOffset, to: now) {
                let weekday = calendar.component(.weekday, from: futureDate)
                let slots = (weekday == 1 || weekday == 7) ? 
                    AppConfig.LimitedTimeDiscount.weekendTimeSlots : 
                    AppConfig.LimitedTimeDiscount.weekdayTimeSlots
                
                if let firstSlot = slots.first {
                    let startTime = timeStringToDate(firstSlot.start, on: futureDate)
                    return startTime
                }
            }
        }
        
        return nil
    }
    
    // MARK: - Private Methods
    
    private func startTimer() {
        timer = Timer.scheduledTimer(withTimeInterval: 60, repeats: true) { _ in
            self.updateDiscountStatus()
        }
    }
    
    private func updateDiscountStatus() {
        DispatchQueue.main.async {
            self.isDiscountActive = self.isCurrentlyInDiscountPeriod()
            self.nextDiscountTime = self.getNextDiscountPeriod()
        }
    }
    
    private func getCurrentTimeString(from date: Date) -> String {
        let formatter = DateFormatter()
        formatter.dateFormat = "HH:mm"
        return formatter.string(from: date)
    }
    
    private func isTimeInSlots(_ timeString: String, slots: [(start: String, end: String)]) -> Bool {
        let currentMinutes = timeStringToMinutes(timeString)
        
        for slot in slots {
            let startMinutes = timeStringToMinutes(slot.start)
            let endMinutes = timeStringToMinutes(slot.end)
            
            if currentMinutes >= startMinutes && currentMinutes < endMinutes {
                return true
            }
        }
        
        return false
    }
    
    private func timeStringToMinutes(_ timeString: String) -> Int {
        let components = timeString.split(separator: ":").compactMap { Int($0) }
        guard components.count == 2 else { return 0 }
        return components[0] * 60 + components[1]
    }
    
    private func timeStringToDate(_ timeString: String, on date: Date) -> Date? {
        let calendar = Calendar.current
        let components = timeString.split(separator: ":").compactMap { Int($0) }
        guard components.count == 2 else { return nil }
        
        var dateComponents = calendar.dateComponents([.year, .month, .day], from: date)
        dateComponents.hour = components[0]
        dateComponents.minute = components[1]
        dateComponents.second = 0
        
        return calendar.date(from: dateComponents)
    }
    
    private func getNextDiscountTimeToday(from date: Date) -> Date? {
        let calendar = Calendar.current
        let weekday = calendar.component(.weekday, from: date)
        let currentTime = getCurrentTimeString(from: date)
        let currentMinutes = timeStringToMinutes(currentTime)
        
        let slots = (weekday == 1 || weekday == 7) ? 
            AppConfig.LimitedTimeDiscount.weekendTimeSlots : 
            AppConfig.LimitedTimeDiscount.weekdayTimeSlots
        
        for slot in slots {
            let startMinutes = timeStringToMinutes(slot.start)
            if currentMinutes < startMinutes {
                return timeStringToDate(slot.start, on: date)
            }
        }
        
        return nil
    }
}